package zack.project.domain.activity.service.partake;

import zack.project.domain.activity.adapter.repository.IActivityRepository;
import zack.project.domain.activity.model.aggregate.CreatePartakeOrderAggregate;
import zack.project.domain.activity.model.entity.ActivityEntity;
import zack.project.domain.activity.model.entity.PartakeRaffleActivityEntity;
import zack.project.domain.activity.model.entity.UserRaffleOrderEntity;
import zack.project.domain.activity.model.valobj.ActivityStateVO;
import zack.project.domain.activity.service.IRaffleActivityPartakeService;
import zack.project.types.enums.ResponseCode;
import zack.project.types.exception.AppException;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

/**参与抽奖活动的抽象类
 * @author A1793
 */
@Slf4j
public abstract class AbstractRaffleActivityPartake implements IRaffleActivityPartakeService {

    protected final IActivityRepository activityRepository;

    public AbstractRaffleActivityPartake(IActivityRepository activityRepository) {
        this.activityRepository = activityRepository;
    }

    /**
     * 更新{raffle_activity_account，raffle_activity_account_day,raffle_activity_account_month}账户参与活动次数的余量
     * 并保存(未使用或新生成的)抽奖单{user_raffle_order}
     * @param partakeRaffleActivityEntity
     * @return
     */
    @Override
    public UserRaffleOrderEntity createOrder(PartakeRaffleActivityEntity partakeRaffleActivityEntity) {

        String userId = partakeRaffleActivityEntity.getUserId();
        Long activityId = partakeRaffleActivityEntity.getActivityId();
        //参数校验
        if (userId == null || activityId == null) {
            throw new AppException(ResponseCode.ACTIVITY_STATE_ERROR.getCode(), ResponseCode.ACTIVITY_STATE_ERROR.getInfo());
        }
        Date curTime = new Date();
        log.info("创建活动抽奖单开始 userId:{} activityId:{}", userId, activityId);
        //根据活动id查找活动配置，用于后续的活动时间和活动状态(开启/关闭)检验
        ActivityEntity activityEntity = activityRepository.queryRaffleActivityByActivityId(activityId);
        //判断活动开启状态，只可以参加开启的活动
        if (!ActivityStateVO.open.equals(activityEntity.getState())) {
            log.error("创建活动抽奖单失败，活动状态未开启 activityId:{} state:{}", activityId, activityEntity.getState());

            throw new AppException(ResponseCode.ACTIVITY_STATE_ERROR.getCode(), ResponseCode.ACTIVITY_STATE_ERROR.getInfo());
        }
        //判断活动时间
        if (activityEntity.getBeginDateTime().after(curTime) || activityEntity.getEndDateTime().before(curTime)) {
            throw new AppException(ResponseCode.ACTIVITY_DATE_ERROR.getCode(), ResponseCode.ACTIVITY_DATE_ERROR.getInfo());
        }
        //判断是否有未消费的抽奖订单，有则返回
        UserRaffleOrderEntity userRaffleOrderEntity =
                activityRepository.queryNoUsedRaffleOrder(partakeRaffleActivityEntity);
        if (userRaffleOrderEntity != null) {
            log.info("创建参与活动订单存在 userId:{} activityId:{} userRaffleOrderEntity:{}", userId, activityId, JSON.toJSONString(userRaffleOrderEntity));
            return userRaffleOrderEntity;
        }
        //走到这一步说明没有未消费订单，需要走扣减用户额度，创建参与活动的聚合实体(参与抽奖活动的总，日，月账户还有抽奖单)
        //用户参与抽奖的账户在一个活动下有一个
        CreatePartakeOrderAggregate createPartakeOrderAggregate = doFilterAccount(userId, activityId, curTime);
        //构建抽奖单
        userRaffleOrderEntity = buildUserRaffleOrder(userId, activityId, curTime);
        createPartakeOrderAggregate.setUserRaffleOrderEntity(userRaffleOrderEntity);
         //把聚合对象传给仓储层，进行对user_raffle_order表和account,account_day,account_month表进行事务操作
        activityRepository.saveCreatePartakeOrderAggregate(createPartakeOrderAggregate);
        log.info("创建活动抽奖单完成 userId:{} activityId:{} orderId:{}", userId, activityId, userRaffleOrderEntity.getOrderId());
        return userRaffleOrderEntity;
    }

    protected abstract CreatePartakeOrderAggregate doFilterAccount(String userId, Long activityId, Date currentDate);

    protected abstract UserRaffleOrderEntity buildUserRaffleOrder(String userId, Long activityId, Date currentDate);


}
